﻿using System.Collections.Generic;

public class ZLoaderQueen : EventSub, IZUpdate
{
    //加载的时候先把ZLoder对象从reqLoaders拿到curLoaders再调用对象的加载(loadNext操作)
    private List<ZLoader> curLoaders;
    //请求列表，加载的时候先AddLoad把Loader加到reqLoaders，然后发起加载，把reqLoaders中的Loader放到curLoaders
    private List<ZLoader> reqLoaders;

    //存储等待节点
    private Dictionary<string, bool> waitLoaders;
    private Dictionary<string, bool> nowLoaders;
    
    private ZQueenModel queenModel;
    private ZLoader curLoader;
    public string loaderName;

    //最大并行加载数量
    public int MaxLoadNum { private get; set; }

    public ZLoader CurLoader { get { return curLoader; } }
    public ZQueenModel QueenModel { get { return queenModel; } }

    public ZLoaderQueen(string name, int maxLoadNum = 1)
    {
        loaderName = name; MaxLoadNum = maxLoadNum;
        waitLoaders = new Dictionary<string, bool>();
        nowLoaders = new Dictionary<string, bool>();

        curLoaders = new List<ZLoader>();
        queenModel = new ZQueenModel();
        reqLoaders = new List<ZLoader>();
    }

    public void Add(ZLoader loader)
    {
        string url = loader.Request.url;
        if (url.IndexOf("null") > -1)
        {
            EDebug.LogError("素材名未知！" + url);
        }

        if (!waitLoaders.ContainsKey(url) 
            && !nowLoaders.ContainsKey(url))
        {
            reqLoaders.Add(loader);
            waitLoaders[url] = true;
            queenModel.TotalFileNum++;
        }
    }

    public void Load()
    {
        queenModel.isQueening = true;
        //从count开始循环，意思就是加满
        for (int i = curLoaders.Count; i < MaxLoadNum; i++)
        {
            if (reqLoaders.Count > 0)
            {
                LoadNext();
            }
        }
    }

    private void LoadNext()
    {
        if (reqLoaders.Count == 0)
        {
            if (curLoaders.Count == 0)
            {
                queenModel.End();
            }
            return;
        }

        ZLoader loader = reqLoaders[0];
        curLoaders.Add(loader);
        reqLoaders.RemoveAt(0);
        AddEvents(loader);
        BehaviourUtil.StartCoroutine(loader.Load());
    }

    private void AddEvents(ZLoader loader)
    {
        loader.AddEvent(ConstData.CHANGE, ProgressHandler);
        loader.AddEvent(ConstData.COMPLETE, CompleteHandler);
        loader.AddEvent(ConstData.ERROR, ErrorHandler);
    }

    private void RemoveEvents(ZLoader loader)
    {
        loader.RemoveEvent(ConstData.CHANGE, ProgressHandler);
        loader.RemoveEvent(ConstData.COMPLETE, CompleteHandler);
        loader.RemoveEvent(ConstData.ERROR, ErrorHandler);
    }

    private void ProgressHandler(object sender, EventArg eventArg)
    {
        curLoader = sender as ZLoader;
        queenModel.OnProgress(curLoader.Progress);
    }

    private void ErrorHandler(object sender, EventArg eventArg)
    {
        if (!ABCheckUpdate.GetSingleton().updated)
        {
            LoadBoardMgr.GetSingleton().ShowUpdate();
            LoadBoardMgr.GetSingleton().DisNoLink();
        }
        else
        {
            BroadEvent(eventArg);
            CompleteHandler(sender, eventArg);
        }
    }

    private void CompleteHandler(object sender, EventArg eventArg)
    {
        if (sender != null)
        {
            curLoader = sender as ZLoader;
        }
        RemoveEvents(curLoader);
        nowLoaders[curLoader.Request.url] = true;
        waitLoaders[curLoader.Request.url] = false;

        curLoaders.Remove(curLoader);
        queenModel.ChildEnd(curLoader);
        curLoader.Clear(); LoadNext();
    }

    public void Clear()
    {
        for (int i = 0; i < curLoaders.Count; i++)
        {
            RemoveEvents(curLoaders[i]);
            curLoaders[i].Clear();
        }
        curLoaders.Clear();
        reqLoaders.Clear();
        waitLoaders.Clear();
        nowLoaders.Clear();
        queenModel.Reset();
    }

    public void ZUpdate()
    {
        if (queenModel.isQueening)
        {
            for (int i = curLoaders.Count - 1; i >= 0; i--)
            {
                curLoaders[i].Update();
            }
        }
    }
}